'use strict';

const axios = require('axios')
const urlJoin = require('url-join') // 拼接url地址
const semver = require('semver')    // 版本比对

/**
 * 发起npm请求
 * @param npmName npm名称
 * @param registry registry地址
 * @returns {null|Promise<AxiosResponse<any>>}
 */
function getNpmInfo(npmName, registry) {
    if (!npmName) {
        return null
    }
    const registryUrl = registry || getDefaultRegistry()
    // npmInfoUrl = http://registry.npmjs.org/@hjy-cli/core
    const npmInfoUrl = urlJoin(registryUrl, npmName)

    return axios.get(npmInfoUrl).then((response) => {
        if (response.status === 200) {
            return response.data
        }
        return null
    }).catch(err => {
        return Promise.reject(err)
    })
}

/**
 * 获取请求地址
 * @param isOriginal 是否是原生
 * @returns {string}
 */
function getDefaultRegistry(isOriginal = false) {
    return isOriginal ? 'https://registry.npmjs.org' : 'https://registry.npm.taobao.org'
}

/**
 * 获取所有的版本号
 * @param npmName
 * @param registry
 * @returns {Promise<string[]|*[]>}
 */
async function getNpmVersions(npmName, registry) {
    // 发起npm请求
    const data = await getNpmInfo(npmName, registry)
    if (data) {
        return Object.keys(data.versions)
    } else {
        return []
    }
}

/**
 * 获取所有满足条件的版本号
 * @param baseVersion 当前版本号
 * @param versions npm地址上的所有版本
 * @returns {*}
 */
function getSemverVersions(baseVersion, versions) {
    // semver.satisfies 满足条件
    return versions
        .filter(version => semver.satisfies(version, `^${baseVersion}`))
        .sort((a, b) => semver.gt(b, a) )
}

/**
 * 拿到最新的版本
 * @param baseVersion
 * @param npmName
 * @param registry
 * @returns {Promise<null|*>}
 */
async function getNpmSemverVersion(baseVersion, npmName, registry) {
    // 获取所有的版本号
    const versions = await getNpmVersions(npmName, registry)
    // 获取所有满足条件的版本号
    const newVersions = getSemverVersions(baseVersion, versions)
    // 返回最新版本
    if (newVersions && newVersions.length > 0) {
        return newVersions[0]
    }
    return null
}

/**
 * 获取npm上最新版本
 * @param npmName
 * @param registry
 * @returns {Promise<null|T>}
 */
async function getNpmLatestVersion(npmName, registry) {
    // 获取所有的版本号
    let versions = await getNpmVersions(npmName, registry)
    if (versions) {
        // gt大于
        return versions.sort((a, b) => semver.gt(b, a))[0]
    }
    return null
}

module.exports = {
    getNpmInfo,
    getNpmVersions,
    getNpmSemverVersion,
    getDefaultRegistry,
    getNpmLatestVersion
};